package com.jsean.web;

import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Properties;

@Slf4j
public class FileClient extends WebSocketClient {
    public FileClient(URI serverUri) {
        super(serverUri);
    }

    static Properties props = new Properties();
    private String basePath;
    private static final String FILE_TRANSFER_FINISH = "FILE_TRANSFER_FINISH";
    private String KEYWORD = "^^";

    @Override
    public void onOpen(ServerHandshake handshakedata) {
        log.info("Connected to server");
    }

    @Override
    public void onMessage(String message) {
        log.info("Received string message");
        if (message.startsWith(FILE_TRANSFER_FINISH)) {
            log.info("close file");
            try {
                downloadFileStream.close();
                this.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private FileOutputStream downloadFileStream;

    public void onMessage(ByteBuffer bytes) {
        log.info("Received binary message, length: {}" ,bytes.remaining());
        // 处理 byte[] 数据
        byte[] data = new byte[bytes.remaining()];
        bytes.get(data);
        try {
            downloadFileStream.write(data);
        } catch (IOException e) {
            e.printStackTrace();
            try {
                if (downloadFileStream != null) {
                    downloadFileStream.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        log.info("Connection closed: " + reason);
    }

    @Override
    public void onError(Exception ex) {
        ex.printStackTrace();
    }

    public void requestFileDownload(String fileName) {
        try {
            while (!this.isOpen()) {
                log.info("Connection not established yet");
                Thread.sleep(1000L);
            }
            String localFile = basePath + File.separatorChar + fileName;
            downloadFileStream = new FileOutputStream(localFile);
            log.info("Preparing to download: " + fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }

        this.send("DOWNLOAD_REQUEST" + KEYWORD + fileName);
    }

    private static String getAppConfig(String key, String defaultValue) {
        try (InputStream is = FileServer.class.getClassLoader().getResourceAsStream("application.properties")) {
            props.load(is);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        String ret = props.getProperty(key, "8090");
        if (ret == null) {
            return defaultValue;
        } else {
            return ret;
        }
    }

    public void initialize(String base) {
        basePath = base;
    }

    public static void main(String[] args) {
        try {
            String ip = getAppConfig("app.ip", "127.0.0.1");
            int port = Integer.parseInt(getAppConfig("app.port", "8090"));
            String base = getAppConfig("app.client.base", "/root");
            FileClient client = new FileClient(new URI("ws://" + ip + ":" + port));
            client.connect();
            client.initialize(base);
            
            // Example usage:
            String fileName = "file.txt";
            if (args.length != 0) {
                fileName = args[1];
            }

            client.requestFileDownload(fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}